package com.jingxuan.util;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import com.jingxuan.util.RankAlgorithm.CommentInfo;
import com.jingxuan.util.RankAlgorithm.ProductFeature;
import com.jingxuan.util.RankAlgorithm.RecommendationResult;
import com.jingxuan.util.RankAlgorithm.ScoredProduct;

import lombok.AccessLevel;
import lombok.Setter;

/**
 * 基于四个评估维度的产品推荐评分算法。
 * 
 * 优化后的评分维度：
 * 1. 价格评分：30 + 70 × (最高价 - 当前价) ÷ (最高价 - 最低价)
 * 2. 口碑评分：0.6 × 好评率分 + 0.4 × 评论质量分
 * 3. 热度评分：0.4 × 评论数量分 + 0.3 × 加购热度分 + 0.3 × 回头客分
 * 4. 时效评分：0.7 × 评论时效分 + 0.3 × 商品新鲜度分
 * 
 * 权重配置（固定）：
 * - 价格权重：0.25
 * - 口碑权重：0.35
 * - 热度权重：0.25
 * - 时效权重：0.15
 */
public final class ProductsRecommendAlgorithm {

    private ProductsRecommendAlgorithm() {}

    // 固定权重配置
    private static final double PRICE_WEIGHT = 0.25;
    private static final double REPUTATION_WEIGHT = 0.35;
    private static final double HEAT_WEIGHT = 0.25;
    private static final double TIMELINESS_WEIGHT = 0.15;

    /**
     * 计算给定产品特征的推荐得分。
     */
    public static RecommendationResult recommend(List<ProductFeature> productFeatures,
                                                 List<String> userPreferenceTags) {
        return recommend(productFeatures, userPreferenceTags, LocalDateTime.now());
    }

    public static RecommendationResult recommend(List<ProductFeature> productFeatures,
                                                 List<String> userPreferenceTags,
                                                 LocalDateTime referenceTime) {
        // 参数验证
        if (productFeatures == null || productFeatures.isEmpty()) {
            return RecommendationResult.empty();
        }

        LocalDateTime now = referenceTime == null ? LocalDateTime.now() : referenceTime;
        
        // 过滤null元素
        List<ProductFeature> features = new ArrayList<>(productFeatures.size());
        for (ProductFeature feature : productFeatures) {
            if (feature != null) {
                features.add(feature);
            }
        }
        if (features.isEmpty()) {
            return RecommendationResult.empty();
        }

        // 1. 计算价格的最值用于归一化
        double minPrice = Double.POSITIVE_INFINITY;
        double maxPrice = Double.NEGATIVE_INFINITY;

        for (ProductFeature feature : features) {
            double price = feature.getPrice() != null ? feature.getPrice().doubleValue() : 0.0;
            // 忽略异常价格（如0或极小值，这里简单处理，可视业务需求增加）
            if (price > 0) {
                minPrice = Math.min(minPrice, price);
                maxPrice = Math.max(maxPrice, price);
            }
        }
        
        // 边界处理：如果没有有效价格或最大最小相等
        if (Double.isInfinite(minPrice) || Double.isInfinite(maxPrice)) {
            minPrice = 0;
            maxPrice = 0;
        }

        // 2. 计算每个产品的各维度得分
        List<ScoredProduct> scoredProducts = new ArrayList<>(features.size());

        for (ProductFeature feature : features) {
            // 价格评分
            double priceScore = RankAlgorithm.calculatePriceScore(
                feature.getPrice(), 
                BigDecimal.valueOf(minPrice), 
                BigDecimal.valueOf(maxPrice)
            );

            // 口碑评分
            double goodRate = feature.getGoodRate() != null ? feature.getGoodRate() * 100 : 75.0; // 默认75
            List<CommentInfo> comments = feature.getComments() != null ? feature.getComments() : Collections.emptyList();
            double detailScore = RankAlgorithm.calculateCommentDetailScore(comments);
            double sentimentScore = RankAlgorithm.calculateSentimentScore(comments);
            double infoValueScore = RankAlgorithm.calculateInformationValueScore(comments);
            
            double reputationScore = RankAlgorithm.calculateReputationScore(goodRate, detailScore, sentimentScore, infoValueScore);

            // 热度评分
            int commentCount = feature.getCommentCount();
            int cartCount = feature.getCartCount() != null ? feature.getCartCount() : 0;
            int returnCount = feature.getReturnCustomerCount() != null ? feature.getReturnCustomerCount() : 0;
            
            double heatScore = RankAlgorithm.calculateHeatScore(commentCount, cartCount, returnCount);

            // 时效评分
            double timelinessScore = RankAlgorithm.calculateTimelinessScore(
                feature.getLastCommentTime(), 
                now, 
                feature.getProductName(), 
                feature.getDescription()
            );

            ScoredProduct scored = new ScoredProduct(feature, priceScore, reputationScore, heatScore, 0.0, timelinessScore);
            
            // 3. 计算综合得分
            // 基础得分 = 加权和
            double baseScore = PRICE_WEIGHT * priceScore + 
                               REPUTATION_WEIGHT * reputationScore + 
                               HEAT_WEIGHT * heatScore + 
                               TIMELINESS_WEIGHT * timelinessScore;
            
            // 标签加权
            double tagBonus = calculateTagMatchBonus(feature.getProductType(), userPreferenceTags);
            
            double finalScore = Math.min(100.0, baseScore + tagBonus);

            setScores(scored, baseScore, 0.0, tagBonus, finalScore);
            
            scoredProducts.add(scored);
        }

        // 4. 排序
        scoredProducts.sort(Comparator.comparingDouble(ScoredProduct::getFinalScore).reversed());

        return new RecommendationResult(
            Collections.unmodifiableList(scoredProducts), 
            new double[]{PRICE_WEIGHT, REPUTATION_WEIGHT, HEAT_WEIGHT, TIMELINESS_WEIGHT}, 
            new double[]{0,0,0,0} // No user preference weights used
        );
    }
    
    private static void setScores(ScoredProduct p, double base, double pref, double tag, double finalS) {
        p.setBaseScore(base);
        p.setPreferenceScore(pref);
        p.setTagBonus(tag);
        p.setFinalScore(finalS);
    }

    private static double calculateTagMatchBonus(String productType, List<String> userPreferenceTags) {
        if (userPreferenceTags == null || userPreferenceTags.isEmpty() || productType == null) {
            return 0.0;
        }
        for (String tag : userPreferenceTags) {
            if (tag != null && tag.trim().equalsIgnoreCase(productType.trim())) {
                return 5.0; // Simple small bonus
            }
        }
        return 0.0;
    }
}
